package besta.moon.engine.index;

import java.nio.channels.FileChannel;
import java.sql.SQLException;

import besta.moon.engine.store.MemoryStream;
import besta.moon.engine.store.MoonImpl;
import besta.moon.engine.store.MoonPage;
import besta.moon.sql.parser.SQLTokenizer;
import besta.moon.engine.IndexNode;

public class FileIndexNode extends IndexNode {

    private final FileChannel file;
    private long fileOffset;

    FileIndexNode(boolean unique, char digit, FileChannel file) {
        super(unique, digit);
        this.file = file;
        fileOffset = -1;
    }

    @Override
    public IndexNode createIndexNode(boolean unique, char digit) {
        return new FileIndexNode(unique, digit, file);
    }

    void save() throws SQLException {
        MoonPage storePage = new MoonPage(null, -1, file, fileOffset);
        MoonImpl store = MoonImpl.createStore(null, storePage, SQLTokenizer.INSERT, fileOffset);
        save(store);
        fileOffset = store.writeFinsh(null);
    }

    @Override
    public void saveRef(MoonImpl output) throws SQLException {
        if (fileOffset < 0) {
            save();
        }
        output.writeLong(fileOffset);
    }

    IndexNode loadRef(long offset) throws SQLException {
        MoonPage storePage = new MoonPage(null, -1, file, offset);
        MoonImpl store = MoonImpl.createStore(null, storePage, SQLTokenizer.INSERT, fileOffset);
        MemoryStream input = new MemoryStream();
        FileIndexNode node = new FileIndexNode(getUnique(), (char) input.readShort(), file);
        node.fileOffset = offset;
        node.load(store);
        return node;
    }

    static FileIndexNode loadRootNode(boolean unique, FileChannel file, long offset) throws Exception {
        MoonPage storePage = new MoonPage(null, -1, file, offset);
        MoonImpl store = MoonImpl.createStore(null, storePage, SQLTokenizer.SELECT, offset);
        FileIndexNode node = new FileIndexNode(unique, (char) store.readShort(), file);
        node.fileOffset = offset;
        node.load(store);
        return node;
    }
}
